<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      padding: 0;
      margin: 0;
    }

    .box {
      width: 150px;
      height: 150px;
      background-color: #6ff;
      position: absolute;
      left: 100px;
      top: 100px;
    }
  </style>
</head>

<body>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</body>
<script>

  // 需求 拖拽盒子移动  松开时盒子停留在当前位置

  // onmousedown  先按下,记录按下的位置(移动需要)
  // onmousemove  再移动, 元素跟随鼠标移动 
  // onmouseup    再松开, 元素停留在当前位置

  // 面向对象  思想上提升 , 就是将你的需求抽象成一个对象,然后针对这个对象分析其特征(属性)与行为(方法)--这个对象就称之为类(面向对象)

  // 拖拽 = {
  //     target: ele,
  //     dragStart() { }, 记录按下的位置
  //     dragMove() { }, 盒子跟随鼠标移动
  //     dragEnd() { }, 清除移动事件
  // }


  // var box = document.getElementsByClassName("box")[0];


  // 1. posX posY 在dragStart 事件中创建,在 dragMove中无法访问 => 跨作用域传递数据?
  // 解决方法 =>  可以先将数据 存储到对象中 => 使用时,在从对象中取出来

  // 2.  事件中的this指向绑定事件的元素  => 多个函数作用域嵌套,this指向可能出现问题?
  //  如果想让内层函数 范围外层函数的this指向
  //  (1)  传统的方法  提前通过中间变量(_this that) 记录this的指向 ,使用时通过中间变量访问
  //  (2) ES6 箭头函数 可以向外跳一层,访问父作用域的this




  // 创建构造函数
  function DragEle(ele) {
    // {}
    // this -> {}

    this.target = ele;

    // this.[[prototype]]  = DragEle.prototype;
    // return this;
  }



  // 绑定公共属性和方法
  DragEle.prototype.init = function () {
    // this ->指向调用此方法的实例化对象
    this.randColor();
    this.dragStart();
  }
  DragEle.prototype.dragStart = function () {
    // this ->指向调用此方法的实例化对象
    // this -> obj
    var _this = this;  // _this => obj
    this.target.onmousedown = function (e) {
      var e = e || window.event;
      var posX = e.offsetX;
      var posY = e.offsetY;
      console.log(posX, posY);

      // console.log(this);   // this指向绑定事件的元素  box
      // console.log(_this);  // 自己没有 访问父作用域 => _this => obj

      _this.posX = posX;
      _this.posY = posY;
      // console.log(_this);

      // 先按下 在移动
      _this.dragMove();
      _this.dragEnd();
    }
  }
  DragEle.prototype.dragMove = function () {
    // this ->指向调用此方法的实例化对象
    var _this = this;  // _this => obj    
    document.onmousemove = function (e) {
      var e = e || window.event;
      var x = e.pageX - _this.posX;
      var y = e.pageY - _this.posY;
      // console.log(_this);
      _this.target.style.left = x + "px";
      _this.target.style.top = y + "px";
    }
  }
  DragEle.prototype.dragEnd = function () {
    document.onmouseup = function () {
      document.onmousemove = null;
    }
  }
  DragEle.prototype.randColor = function () {
    var str = "0123456789abcdef";
    var colorStr = "#";
    for (var i = 0; i < 6; i++) {
      var index = Math.floor(Math.random() * str.length);
      var char = str.charAt(index);
      colorStr += char;
    }
    this.target.style.backgroundColor = colorStr;
  }

  console.dir(DragEle)



  var boxList = document.getElementsByClassName("box");
  for (let i = 0; i < boxList.length; i++) {
    let box = boxList[i];
    var result = new DragEle(box);
    console.log(result);
    result.init();
  }








</script>

</html>